home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / muds / lpmud312.tar / lpmud312 / comm1.c < prev    next >
C/C++ Source or Header  |  1993-01-11  |  40KB  |  1,638 lines

  1. #include <sys/types.h>
  2. #include <sys/time.h>
  3. #include <sys/ioctl.h>
  4. #define    TELOPTS
  5. #include <arpa/telnet.h>
  6. #include <netdb.h>
  7. #include <stdio.h>
  8. #include <errno.h>
  9. #include <string.h>
  10. #include <ctype.h>
  11. #include <signal.h>
  12. #include <memory.h>
  13. #ifndef sun
  14. #include <fcntl.h>
  15. #endif
  16. #ifdef _AIX
  17. #include <sys/select.h>
  18. #endif
  19. #include "config.h"
  20. #include "lint.h"
  21. #include "interpret.h"
  22. #include "comm.h"
  23. #include "object.h"
  24. #include "sent.h"
  25. #include "patchlevel.h"
  26. #include "wiz_list.h"
  27.  
  28. #ifdef MUDWHO
  29. #include "mudwho.h"
  30. #endif
  31.  
  32. #ifdef MSDOS
  33. #include "msdos/pcomm.h"
  34. #endif
  35.  
  36. int socket PROT((int, int, int));
  37. #ifndef sgi
  38. #ifdef NeXT
  39. int setsockopt PROT((int, int, int, void *, int));
  40. #else
  41. #ifndef linux
  42. int setsockopt PROT((int, int, int, char *, int));
  43. #endif
  44. #endif
  45. int bind PROT((int, struct sockaddr *, int));
  46. int listen PROT((int, int));
  47. int accept PROT((int, struct sockaddr *, int *));
  48. #endif /* sgi */
  49. #ifndef linux
  50. int select PROT((int, fd_set *, fd_set *, fd_set *, struct timeval *));
  51. void bzero PROT((char *, int));
  52. #endif
  53.  
  54. void telnet_neg PROT((char *, char *));
  55. void set_prompt PROT((char *));
  56. char *query_ip_number PROT((struct object *));
  57. static void add_ip_entry PROT((long, char *));
  58.  
  59. extern char *xalloc(), *string_copy(), *unshared_str_copy();
  60. extern int d_flag;
  61. extern int current_time;
  62. char * first_cmd_in_buf PROT((struct interactive *));
  63. void next_cmd_in_buf PROT((struct interactive *));
  64. char * skip_eols PROT((struct interactive *, char *));
  65. void remove_flush_entry PROT((struct interactive *ip));
  66.  
  67. void remove_interactive(), add_ref();
  68.  
  69. extern void debug_message(), fatal(), free_sentence();
  70.  
  71. struct interactive *all_players[MAX_PLAYERS];
  72.  
  73. extern int errno;
  74.  
  75. void new_player();
  76.  
  77. void flush_all_player_mess();
  78.  
  79. fd_set readfds;
  80. int nfds = 0;
  81. int num_player;
  82.  
  83. FILE *f_ip_demon = NULL, *f_ip_demon_wr;
  84.  
  85. #ifdef ACCESS_RESTRICTED
  86. extern void *allow_host_access (); 
  87. extern void release_host_access ();
  88. #endif
  89.  
  90. static struct object *first_player_for_flush=(struct object *)NULL;
  91.  
  92. /*
  93.  * Interprocess communication interface to the backend.
  94.  */
  95.  
  96. static int s;
  97. extern int port_number;
  98.  
  99. #ifdef COMM_STAT
  100. int add_message_calls=0;
  101. int inet_packets=0;
  102. int inet_volume=0;
  103. #endif
  104.  
  105. void prepare_ipc() {
  106. #ifndef MSDOS
  107.     struct sockaddr_in sin;
  108.     struct hostent *hp;
  109.     int tmp;
  110.     char host_name[100];
  111. #ifdef MUDWHO
  112.     char buff[100];
  113. #endif
  114.  
  115.     if (gethostname(host_name, sizeof host_name) == -1) {
  116.         perror("gethostname");
  117.     fatal("Error in gethostname()\n");
  118.     }
  119.     hp = gethostbyname(host_name);
  120.     if (hp == 0) {
  121.     (void)fprintf(stderr, "gethostbyname: unknown host.\n");
  122.     exit(1);
  123.     }
  124.     memset((char *)&sin, '\0', sizeof sin);
  125.     memcpy((char *)&sin.sin_addr, hp->h_addr, hp->h_length);
  126.     sin.sin_port = htons((u_short)port_number);
  127.     sin.sin_family = hp->h_addrtype;
  128.     sin.sin_addr.s_addr = INADDR_ANY;
  129.     s = socket(hp->h_addrtype, SOCK_STREAM, 0);
  130.     if (s == -1) {
  131.     perror("socket");
  132.     abort();
  133.     }
  134.     tmp = 1;
  135.     if (setsockopt (s, SOL_SOCKET, SO_REUSEADDR,
  136.             (char *) &tmp, sizeof (tmp)) < 0) {
  137.     perror ("setsockopt");
  138.     exit (1);
  139.     }
  140.     if (bind(s, (struct sockaddr *)&sin, sizeof sin) == -1) {
  141.     if (errno == EADDRINUSE) {
  142.         fprintf(stderr, "Socket already bound!\n");
  143.         debug_message("Socket already bound!\n");
  144.         exit(errno);
  145.     } else {
  146.         perror("bind");
  147.         abort();
  148.     }
  149.     }
  150.     if (listen(s, 5) == -1) {
  151.     perror("listen");
  152.     abort();
  153.     }
  154.     tmp = 1;
  155. #if defined(sun) || defined(M_UNIX) || defined(NeXT)
  156.     if (ioctl(s, FIONBIO, &tmp) == -1) {
  157.     perror("ioctl socket FIONBIO");
  158.     abort();
  159.     }
  160. #else /* sun or linux */
  161. #ifdef linux
  162.     if (fcntl(s, F_SETFL, O_NDELAY) == -1) {
  163.     perror("ioctl socket FIONBIO");
  164.     abort();
  165.     }
  166. #else /* sun */
  167.     if (fcntl(s, F_SETFL, FNDELAY) == -1) {
  168.     perror("ioctl socket FIONBIO");
  169.     abort();
  170.     }
  171. #endif /* sun */
  172. #endif /* sun or linux */
  173.     signal(SIGPIPE, SIG_IGN);
  174. #ifdef MUDWHO
  175.     sprintf(buff, "3.00.%02d", PATCH_LEVEL);
  176.     rwhocli_setup(MUDWHO_SERVER,MUDWHO_PASSWORD,MUDWHO_NAME,buff);
  177. #endif
  178. #else
  179.     c_listen();
  180. #endif
  181. }
  182.  
  183. /*
  184.  * This one is called when shutting down the MUD.
  185.  */
  186. void ipc_remove() {
  187.     (void)printf("Shutting down ipc...\n");
  188. #ifndef MSDOS
  189.     close(s);
  190. #ifdef MUDWHO
  191.     rwhocli_shutdown();
  192. #endif
  193. #else
  194.     c_shutdown();
  195. #endif
  196. }
  197.  
  198. /*
  199.  * Send a message to a player. If that player is shadowed, special
  200.  * care hs tobe taken.
  201.  */
  202. /*VARARGS1*/
  203. void add_message(fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
  204.     char *fmt;
  205.     int a1, a2, a3, a4, a5, a6, a7, a8, a9;
  206. {
  207.     char buff[10000];        /* Kludgy! Hope this is enough ! */
  208.     char buff2[MAX_SOCKET_PACKET_SIZE+1];
  209.     struct interactive *ip;
  210.     int n, chunk, length;
  211.     int from, to;
  212.     int min_length;
  213.     int old_message_length;
  214.  
  215.     if (command_giver == 0 || (command_giver->flags & O_DESTRUCTED) ||
  216.     command_giver->interactive == 0 ||
  217.     command_giver->interactive->do_close) {
  218.     putchar(']');
  219.     if ( fmt != MESSAGE_FLUSH )
  220.         printf(fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
  221.     fflush(stdout);
  222.     return;
  223.     }
  224.     ip = command_giver->interactive;
  225.     old_message_length = ip->message_length;
  226.     if ( fmt == MESSAGE_FLUSH ) {
  227.     min_length = 1;
  228.     strncpy ( buff, ip->message_buf, length=old_message_length );
  229.         buff[length] = '\0';
  230.     } else {
  231. #ifdef COMM_STAT
  232.     add_message_calls++; /* We want to know how many packets the old
  233.                 version would have sent             */
  234. #endif
  235.     min_length = DESIRED_SOCKET_PACKET_SIZE;
  236.     (void)sprintf(buff+old_message_length,fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);
  237.     length = old_message_length + strlen(buff+old_message_length);
  238.     /*
  239.      * Always check that your arrays are big enough ! :-)
  240.      */
  241.     if (length > sizeof buff)
  242.         fatal("To long message!\n");
  243.     if (shadow_catch_message(command_giver, buff+old_message_length))
  244.         return;
  245.     if (ip->snoop_by) {
  246.         struct object *save = command_giver;
  247.         command_giver = ip->snoop_by->ob;
  248.         add_message("%%%s", buff+old_message_length);
  249.         command_giver = save;
  250.     }
  251.     if ( length >= min_length ) {
  252.         strncpy ( buff, ip->message_buf, old_message_length );
  253.     } else {
  254.         strcpy( ip->message_buf+old_message_length,
  255.         buff+old_message_length );
  256.     }
  257.     }
  258.     if (d_flag > 1)
  259.     debug_message("[%s(%d)]: %s", command_giver->name, length, buff);
  260.     /*
  261.      * Insert CR after all NL.
  262.      */
  263.     to = 0;
  264. #ifdef PORTALS
  265.     if (ip->out_portal) {
  266.     buff2[0] = ']';
  267.     to = 1;
  268.     }
  269. #endif
  270.     for (from = 0; length-from >= min_length; to = 0 ) {
  271.     for ( ; to < (sizeof buff2)-1 && buff[from] != '\0';) {
  272.         if (buff[from] == '\n')
  273.         buff2[to++] = '\r';
  274. #if 0
  275.         if (isprint(buff[from]) || isspace(buff[from]))
  276.         buff2[to++] = buff[from++];
  277.         else
  278.         from++;
  279. #else
  280.         buff2[to++] = buff[from++];
  281. #endif
  282.     }
  283.     if ( to == sizeof(buff2) ) {
  284.         to -= 2;
  285.         from--;
  286.     }
  287.     chunk = to;
  288.     /*
  289.      * We split up the message into something smaller than the max size.
  290.      */
  291.     if ((n = write(ip->socket, buff2, chunk)) == -1) {
  292.         if (errno == EMSGSIZE) {
  293.         fprintf(stderr, "comm1: write EMSGSIZE.\n");
  294.         return;
  295.         }
  296.         if (errno == EINVAL) {
  297.         fprintf(stderr, "comm1: write EINVAL.\n");
  298.             if (old_message_length) remove_flush_entry(ip);
  299.         ip->do_close = 1;
  300.         return;
  301.         }
  302.         if (errno == ENETUNREACH) {
  303.         fprintf(stderr, "comm1: write ENETUNREACH.\n");
  304.             if (old_message_length) remove_flush_entry(ip);
  305.         ip->do_close = 1;
  306.         return;
  307.         }
  308.         if (errno == EHOSTUNREACH) {
  309.         fprintf(stderr, "comm1: write EHOSTUNREACH.\n");
  310.             if (old_message_length) remove_flush_entry(ip);
  311.         ip->do_close = 1;
  312.         return;
  313.         }
  314.         if (errno == EPIPE) {
  315.         fprintf(stderr, "comm1: write EPIPE detected\n");
  316.             if (old_message_length) remove_flush_entry(ip);
  317.         ip->do_close = 1;
  318.         return;
  319.         }
  320.         if (errno == EWOULDBLOCK) {
  321.         fprintf(stderr, "comm1: write EWOULDBLOCK. Message discarded.\n");
  322.             if (old_message_length) remove_flush_entry(ip);
  323. /*        ip->do_close = 1;  -- LA */
  324.         return;
  325.         }
  326.         fprintf(stderr, "write: unknown errno %d\n", errno);
  327.         perror("write");
  328.         if (old_message_length) remove_flush_entry(ip);
  329.         ip->do_close = 1;
  330.         return;
  331.     }
  332. #ifdef COMM_STAT
  333.     inet_packets++;
  334.     inet_volume += n;
  335. #endif
  336.     if (n != chunk)
  337.         fprintf(stderr, "write socket: wrote %d, should be %d.\n",
  338.             n, chunk);
  339.     continue;
  340.     }
  341.     length -= from;
  342.     ip->message_length=length;
  343.     if (from)
  344.         strncpy( ip->message_buf, buff+from, length );
  345.     if ( length && !old_message_length ) { /* buffer became 'dirty' */
  346.     if ( ip->next_player_for_flush = first_player_for_flush ) {
  347.         first_player_for_flush->interactive->previous_player_for_flush =
  348.         command_giver;
  349.     }
  350.     ip->previous_player_for_flush = 0;
  351.     first_player_for_flush = command_giver;
  352.     }
  353.     if ( !length && old_message_length ) { /* buffer has become empty */
  354.     remove_flush_entry(ip);
  355.     }
  356. }
  357.  
  358. void remove_flush_entry(ip)
  359.     struct interactive *ip;
  360. {
  361.  
  362.     ip->message_length=0;
  363.     if ( ip->previous_player_for_flush ) {
  364.     ip->previous_player_for_flush->interactive->next_player_for_flush
  365.     = ip->next_player_for_flush;
  366.     } else {
  367.     first_player_for_flush = ip->next_player_for_flush;
  368.     }
  369.     if ( ip->next_player_for_flush ) {
  370.     ip->next_player_for_flush->interactive->previous_player_for_flush
  371.     = ip->previous_player_for_flush;
  372.     }
  373. }
  374.  
  375. void flush_all_player_mess() {
  376.     struct object *p,*np;
  377.     struct object *save = command_giver;
  378.  
  379.     for ( p = first_player_for_flush; p; p=np) {
  380.         np = p->interactive->next_player_for_flush;
  381.     /* beware of side-effects when calling add_message the first time! */
  382.     command_giver = p;
  383.     add_message(MESSAGE_FLUSH);
  384.     }
  385.     command_giver=save;
  386. }
  387.  
  388.  
  389. /*
  390.  * Copy a string, replacing newlines with '\0'. Also add an extra
  391.  * space and back space for every newline. This trick will allow
  392.  * otherwise empty lines, as multiple newlines would be replaced by
  393.  * multiple zeroes only.
  394.  */
  395. static int copy_chars(from, to, n)
  396.     char *from, *to;
  397.     int n;
  398. {
  399.     int i;
  400.     char *start = to;
  401.     for (i=0; i<n; i++) {
  402.     if (from[i] == '\r')
  403.         continue;
  404.     if (from[i] == '\n') {
  405.         *to++ = ' ';
  406.         *to++ = '\b';
  407.         *to++ = '\0';
  408.         continue;
  409.     }
  410.     *to++ = from[i];
  411.     }
  412.     return to - start;
  413. }
  414.  
  415. /*
  416.  * Get a message from any player.  For all players without a completed
  417.  * cmd in their input buffer, read their socket.  Then, return the first
  418.  * cmd of the next player in sequence that has a complete cmd in their buffer.
  419.  * CmdsGiven is used to allow people in ED to send more cmds (if they have
  420.  * them queued up) than normal players.  If we get a heartbeat, still read
  421.  * all sockets; if the next cmd giver is -1, we have already cycled and
  422.  * can go back to do the heart beat.
  423.  */
  424.  
  425. #define    StartCmdGiver    (MAX_PLAYERS-1) /* the one after heartbeat */
  426. #define IncCmdGiver    NextCmdGiver = (NextCmdGiver < 0? StartCmdGiver: \
  427.                     NextCmdGiver - 1)
  428.  
  429. int NextCmdGiver = StartCmdGiver;
  430. int CmdsGiven = 0;     /* -1 is used to poll heart beat. */
  431. int twait = 0;         /* wait time for select() */
  432. extern int time_to_call_heart_beat, comm_time_to_call_heart_beat;
  433.  
  434. int get_message(buff, size)
  435.     char *buff;
  436.     int size;
  437. {
  438.     int i, res;
  439.     struct interactive * ip = 0;
  440.     char *p;
  441.  
  442.     /*
  443.      * Stay in this loop until we have a message from a player.
  444.      */
  445.     while(1) {
  446.     int new_socket;
  447.     struct sockaddr_in addr;
  448.     int length;
  449.     struct timeval timeout;
  450.  
  451.     /* First, try to get a new player... */
  452.     length = sizeof addr;
  453.     new_socket = accept(s, (struct sockaddr *)&addr, &length);
  454.     if (new_socket != -1)
  455.         new_player(new_socket, &addr, length);
  456.     else if (new_socket == -1 && errno != EWOULDBLOCK && errno != EINTR) {
  457.         perror("accept");
  458.         abort();
  459.     }
  460.  
  461.     nfds = 0;
  462.     FD_ZERO(&readfds);
  463.     for (i=0; i<MAX_PLAYERS; i++) {
  464.         ip = all_players[i];
  465.         if (!ip)
  466.         continue;
  467.         if (ip->do_close) {
  468.         ip->do_close = 0;
  469.         remove_interactive(ip->ob);
  470.         continue;
  471.         }
  472.         if (!first_cmd_in_buf(ip)) {
  473.         FD_SET(ip->socket, &readfds);
  474.         if (ip->socket >= nfds)
  475.             nfds = ip->socket+1;
  476. #ifdef PORTALS
  477.         if (ip->out_portal) {
  478.             FD_SET(ip->portal_socket, &readfds);
  479.             if (ip->portal_socket >= nfds)
  480.             nfds = ip->portal_socket + 1;
  481.         }
  482. #endif /* PORTALS */
  483.         }
  484.     }
  485.     if (f_ip_demon != NULL) {
  486.         FD_SET(fileno(f_ip_demon), &readfds);
  487.     }
  488.     timeout.tv_sec = twait; /* avoid busy waiting when no buffered cmds */
  489.     timeout.tv_usec = 0;
  490.     res = select(nfds, &readfds, 0, 0, &timeout);
  491. #ifdef MSDOS
  492.     if (timer_expired()) {
  493.         twait = 0;
  494.         goto return_next_command;
  495.     }
  496. #endif
  497.     if (res == -1) {
  498.         twait = 0;
  499.         if (errno == EINTR) /* if we got an alarm, finish the round */
  500.         goto return_next_command;
  501.         perror("select");
  502.         return 0;
  503.     }
  504.     if (res) { /* waiting packets */
  505.         if (f_ip_demon != NULL && FD_ISSET(fileno(f_ip_demon), &readfds)) {
  506.         char buf[200], *pp, *q;
  507.         long laddr;
  508.         if (fgets(buf, sizeof buf, f_ip_demon)) {
  509. /*printf("hname says: %s\n", buf);*/
  510.             laddr=inet_addr(buf);
  511.             if (laddr != -1) {
  512.             pp = strchr(buf, ' ');
  513.             if (pp) {
  514.                 pp++;
  515.                 q = strchr(buf, '\n');
  516.                 if (q) {
  517.                 *q = 0;
  518.                 add_ip_entry(laddr, pp);
  519.                 }
  520.             }
  521.             }
  522.         }
  523.         }
  524.         for (i=0; i<MAX_PLAYERS; i++) { /* read all pending sockets */
  525.         ip = all_players[i];
  526.         if (ip == 0)
  527.             continue;
  528.         if (FD_ISSET(ip->socket, &readfds)) { /* read this player */
  529.             int l;
  530.  
  531.             /*
  532.              * Don't overfill their buffer.
  533.              * Use a very conservative estimate on how much we can
  534.              * read.
  535.              */
  536.             l = (MAX_TEXT - ip->text_end - 1)/3;
  537.             if (l < size)
  538.             size = l;
  539.  
  540.             if ((l = read(ip->socket, buff, size)) == -1) {
  541.             if (errno == ENETUNREACH) {
  542.                 debug_message("Net unreachable detected.\n");
  543.                 remove_interactive(ip->ob);
  544.                 continue;
  545.             }
  546.             if (errno == EHOSTUNREACH) {
  547.                 debug_message("Host unreachable detected.\n");
  548.                 remove_interactive(ip->ob);
  549.                 continue;
  550.             }
  551.             if (errno == ETIMEDOUT) {
  552.                 debug_message("Connection timed out detected.\n");
  553.                 remove_interactive(ip->ob);
  554.                 continue;
  555.             }
  556.             if (errno == ECONNRESET) {
  557.                 debug_message("Connection reset by peer detected.\n");
  558.                 remove_interactive(ip->ob);
  559.                 continue;
  560.             }
  561.             if (errno == EWOULDBLOCK) {
  562.                 debug_message("read would block socket %d!\n",
  563.                       ip->socket);
  564.                 remove_interactive(ip->ob);
  565.                 continue;
  566.             }
  567.             if (errno == EMSGSIZE) {
  568.                 debug_message("read EMSGSIZE !\n");
  569.                 continue;
  570.             }
  571.             perror("read");
  572.             debug_message("Unknown errno %d\n", errno);
  573.             remove_interactive(ip->ob);
  574.             continue;
  575.             }
  576. #ifdef PORTALS
  577.             /*
  578.              * IF the data goes through a portal, send it,
  579.              * but don't return any data.
  580.              */
  581.             if (ip->out_portal) {
  582.             if (ip->text_end) { /* pending text first */
  583.                 write(ip->portal_socket, ip->text, ip->text_end);
  584.                 ip->text_end = 0;
  585.             }
  586.             if (l)
  587.                 write(ip->portal_socket, buff, l);
  588.             continue;
  589.             }
  590. #endif /* PORTALS */
  591.             if (l == 0) {
  592.             if (ip->closing)
  593.                 fatal("Tried to read from closing socket.\n");
  594.             remove_interactive(ip->ob);
  595.             return 0;
  596.             }
  597.             buff[l] = '\0';
  598.             /* replace newlines by nulls and catenate to buffer */
  599.             ip->text_end +=
  600.             copy_chars(buff, ip->text + ip->text_end, l);
  601. #if 0
  602.             for (x=0; x<l; x++) {
  603.             if (buff[x] == '\n' || buff[x] == '\r')
  604.                 buff[x] = '\0';
  605.             }
  606.             memcpy(ip->text+ip->text_end, buff, l+1);
  607.             ip->text_end += l;
  608. #endif
  609.             /* now, text->end is just after the last char read.  If last */
  610.             /* char was a nl, char *before* text_end will be null. */
  611.             ip->text[ip->text_end] = '\0';
  612.         }
  613.         }
  614.     }
  615.     /*
  616.      * we have read the sockets; now find and return a command
  617.      */
  618.     return_next_command:
  619.     twait = 0;
  620.     ip = 0;
  621.     for (i = 0; i < MAX_PLAYERS + 1; i++) {
  622.         if (NextCmdGiver == -1) { /* we have cycled around all players */
  623.         CmdsGiven = 0;      /* check heart beat */
  624.         IncCmdGiver;
  625.         if (comm_time_to_call_heart_beat) {
  626.             time_to_call_heart_beat = 1; /* twait stays 0! */
  627.             return 0;
  628.         }
  629.         }
  630.         ip = all_players[NextCmdGiver];
  631.         if (ip && (p = first_cmd_in_buf(ip))) /* wont respond to partials */
  632.         break;
  633.         CmdsGiven = 0; /* new player, no cmds issued */
  634.         IncCmdGiver;
  635.     }
  636.     
  637.     if ((!ip)||!p) { /* no cmds found; loop and select (on timeout) again */
  638.         if (comm_time_to_call_heart_beat) { /* may as well do it now */
  639.         time_to_call_heart_beat = 1; /* no cmds, do heart beat */
  640.         NextCmdGiver = StartCmdGiver;/* do a complete poll next time */
  641.         CmdsGiven = 0;
  642.         return(0);
  643.         }
  644.         /* no heart beat to do and no cmds pending - avoid busy wait on select */
  645.         twait = 1;
  646.         continue; /* else await another cmd */
  647.     }
  648.     
  649.     /*
  650.      * we have a player cmd - return it.  If he is in ed, count his
  651.      * cmds, else only allow 1 cmd.  If he has only one partially
  652.      * completed cmd left after * this, move it to the start of his
  653.      * buffer; new stuff will be appended.
  654.      */
  655.     
  656.     command_giver = ip->ob;
  657.     telnet_neg(buff, p);
  658.     next_cmd_in_buf(ip); /* move on buffer pointers */
  659.     
  660.     /* if he is not in ed, dont let him issue another till the poll comes again */
  661.     
  662.     if (ip->ed_buffer && CmdsGiven < ALLOWED_ED_CMDS)
  663.         CmdsGiven++;
  664.     else {
  665.         IncCmdGiver;
  666.         CmdsGiven = 0;
  667.     }
  668.     
  669.     /* manage snooping - should the snooper see type ahead?  Well, he doesn't here
  670.      */
  671.     if (ip->snoop_by && !ip->noecho) {
  672.         command_giver = ip->snoop_by->ob;
  673.         add_message("%% %s\n", buff);
  674.     }
  675.     command_giver = ip->ob;
  676.     if (ip->noecho) {
  677.         /* Must not enable echo before the user input is received. */
  678.         add_message("%c%c%c", IAC, WONT, TELOPT_ECHO);
  679.     }
  680.     ip->noecho = 0;
  681.     ip->last_time = current_time;
  682.     return 1;
  683.     }
  684. }
  685.  
  686. /*
  687.  * find the first character of the next complete cmd in a buffer, 0 if no
  688.  * completed cmd.  There is a completed cmd if there is a null between
  689.  * text_start and text_end.  Zero length commands are discarded (as occur
  690.  * between <cr> and <lf>).  Update text_start if we have to skip leading
  691.  * nulls.
  692.  */
  693.  
  694. char * first_cmd_in_buf(ip) 
  695. struct interactive *ip;
  696. {
  697.     char * p, *q;
  698.  
  699.     p = ip->text_start + ip->text;
  700.  
  701.     while ((p < (ip->text_end + ip->text)) && !*p) /* skip null input */
  702.     p++;
  703.  
  704.     ip->text_start = p - ip->text;
  705.  
  706.     if (ip->text_start >= ip->text_end) {
  707.     ip->text_start = ip->text_end = 0;
  708.     ip->text[0] = '\0';
  709.     return(0);
  710.     }
  711.  
  712.     while ((p < (ip->text_end + ip->text)) && *p) /* find end of cmd */
  713.     p++;
  714.  
  715.     if (p < ip->text + ip->text_end) /* null terminated, was command */
  716.     return(ip->text + ip->text_start);
  717.  
  718. /* have a partial command at end of buffer; move it to start, return null */
  719. /* if it can't move down, truncate it and return it as cmd. */
  720.     
  721.     p = ip->text + ip->text_start;
  722.     q = ip->text;
  723.     while (p < (ip->text + ip->text_end))
  724.     *(q++) = *(p++);
  725.  
  726.     ip->text_end -= ip->text_start;
  727.     ip->text_start = 0;
  728.     if (ip->text_end > MAX_TEXT - 2) {
  729.     ip->text[ip->text_end-2] = '\0'; /* nulls to truncate */
  730.     ip->text[ip->text_end-1] = '\0'; /* nulls to truncate */
  731.     ip->text_end--;
  732.     return(ip->text);
  733.     }
  734. /* buffer not full and no newline - no cmd. */
  735.     return(0);
  736. }
  737.  
  738. /*
  739.  * move pointers to next cmd, or clear buf.
  740.  */
  741.  
  742. void next_cmd_in_buf(ip)
  743. struct interactive *ip;
  744. {
  745.     char * p = ip->text + ip->text_start;
  746.     while (*p && p < ip->text + ip->text_end)
  747.     p++;
  748.     /* skip past any nulls at the end */
  749.     while (!*p && p < ip->text + ip->text_end)
  750.     p++;
  751.     if (p < ip->text + ip->text_end)
  752.     ip->text_start = p - ip->text;
  753.     else {
  754.     ip->text_start = ip->text_end = 0;
  755.     ip->text[0] = '\0';
  756.     }
  757. }
  758.     
  759.  
  760. /*
  761.  * Remove an interactive player immediately.
  762.  */
  763. void remove_interactive(ob)
  764.     struct object *ob;
  765. {
  766.     struct object *save = command_giver;
  767.     int i;
  768.  
  769.     for (i=0; i<MAX_PLAYERS; i++) {
  770.     if (all_players[i] != ob->interactive)
  771.         continue;
  772.     if (ob->interactive->closing)
  773.         fatal("Double call to remove_interactive()\n");
  774.     ob->interactive->closing = 1;
  775.     if (ob->interactive->snoop_by) {
  776.         ob->interactive->snoop_by->snoop_on = 0;
  777.         ob->interactive->snoop_by = 0;
  778.     }
  779.     if (ob->interactive->snoop_on) {
  780.         ob->interactive->snoop_on->snoop_by = 0;
  781.         ob->interactive->snoop_on = 0;
  782.     }
  783.     command_giver = ob;
  784.     add_message("Closing down.\n");
  785.     if (ob->interactive->ed_buffer) {
  786.         extern void save_ed_buffer();
  787.  
  788.         save_ed_buffer();
  789.     }
  790.     add_message(MESSAGE_FLUSH);
  791.     (void)shutdown(ob->interactive->socket, 2);
  792.     close(ob->interactive->socket);
  793. #ifdef ACCESS_RESTRICTED
  794.         release_host_access (ob->interactive->access_class);
  795. #endif
  796.     num_player--;
  797.     if (ob->interactive->input_to) {
  798.         free_object(ob->interactive->input_to->ob, "remove_interactive");
  799.         free_sentence(ob->interactive->input_to);
  800.         ob->interactive->input_to = 0;
  801.     }
  802.     free((char *)ob->interactive);
  803.     ob->interactive = 0;
  804.     all_players[i] = 0;
  805.     free_object(ob, "remove_interactive");
  806.     command_giver = save;
  807.     return;
  808.     }
  809.     (void)fprintf(stderr, "Could not find and remove player %s\n", ob->name);
  810.     abort();
  811. }
  812.  
  813. #ifndef MSDOS
  814. #ifndef ACCESS_RESTRICTED
  815.  
  816. int
  817. allow_host_access(new_socket)
  818.     int new_socket;
  819. {
  820.     struct sockaddr_in apa;
  821.     int len = sizeof apa;
  822.     char * ipname, *calloc(), *xalloc(), *index();
  823.     static int read_access_list = 0;
  824.     static struct access_list {
  825.     int addr_len;
  826.     char * addr, *name, *comment;
  827.     struct access_list * next;
  828.     } * access_list;
  829.     register struct access_list * ap;
  830.  
  831.     if(!read_access_list) {
  832.     FILE * f = fopen("ACCESS.DENY", "r");
  833.     char buf[1024], ipn[50], hname[100], comment[1024], *p1, *p2;
  834.     struct access_list * na;
  835.     struct hostent * hent;
  836.  
  837.     read_access_list = 1;
  838.     if(f) {
  839.         while(fgets(buf, sizeof buf - 1, f)) {
  840.         if(*buf != '#') {
  841.             ipn[0] = hname[0] = comment[0] = 0;
  842.             if(p1 = index(buf, ':')) *p1 = 0;
  843.             if(buf[0] && buf[0] != '\n')
  844.             strncpy(ipn, buf, sizeof ipn - 1);
  845.             if((p2 = p1) && *++p2) {
  846.             if(p1 = index(p2, ':')) *p1 = 0;
  847.             if(p2[0] && p2[0] != '\n')
  848.                 strcpy(hname, p2);
  849.             if(p1 && p1[1] && p1[1] != '\n')
  850.                 strcpy(comment, p1+1);
  851.             }
  852.             
  853.             if(!(na = (struct access_list *)xalloc(sizeof na[0]))) {
  854.             fatal("Out of mem.\n");
  855.             }
  856.             na->addr = na->name = na->comment = 0;
  857.             na->next = 0;
  858.             if(*ipn && (!(na->addr = xalloc(strlen(ipn) + 1)) ||
  859.                 !strcpy(na->addr, ipn)))
  860.             fatal("Out of mem.\n");
  861.             if(*hname && (!(na->name = xalloc(strlen(hname) + 1)) ||
  862.                   !strcpy(na->name, hname)))
  863.             fatal("Out of mem.\n");
  864.             if(*comment && (!(na->comment=xalloc(strlen(comment)+1))||
  865.                     !strcpy(na->comment, comment)))
  866.             fatal("Out of mem.\n");
  867.  
  868.             if((!(int)*ipn)
  869.             &&
  870.             ((!*hname)
  871.               || (!(hent = gethostbyname(hname))) ||
  872.                  (!(na->addr =
  873.                    xalloc(hent->h_length+1)))||
  874.                  !strcpy(na->addr,
  875.                     inet_ntoa(*(struct in_addr *)hent->h_addr)))) {
  876.             if(na->name) free(na->name);
  877.             if(na->comment) free(na->comment);
  878.             free((char *)na);
  879.             continue;
  880.             }
  881.             if(!(na->addr_len = strlen(na->addr)))
  882.             continue;
  883.  
  884.             /* printf("disabling: %s:%s:%s\n", na->addr,
  885.                na->name?na->name:"no name",
  886.                na->comment?na->comment:"no comment");  */
  887.  
  888.             na->next = access_list;
  889.             access_list = na;
  890.         }
  891.         }
  892.         fclose(f);
  893.     }
  894.     }
  895.     
  896.     if (!access_list)
  897.     return 0;
  898.     
  899.     if(getpeername(new_socket, (struct sockaddr *)&apa, &len) == -1) {
  900.     close(new_socket);
  901.     perror("getpeername");
  902.     return -1;
  903.     }
  904.  
  905.     ipname = inet_ntoa(apa.sin_addr);
  906.     
  907.     for(ap = access_list; ap; ap = ap->next)
  908.     if(!strncmp(ipname, ap->addr, ap->addr_len)){
  909.         if(ap->comment) (void) write(new_socket, ap->comment,
  910.                      strlen(ap->comment));
  911.         printf("Stopping: %s:%s\n", ap->addr, ap->name?ap->name:"no name");
  912.         close(new_socket);
  913.         return -1;
  914.     }
  915.     return 0;
  916. }
  917. #endif /* not ACCESS_RESTRICTED */
  918. #endif
  919.  
  920. /*
  921.  * get the I'th player object from the interactive list, i starts at 0
  922.  * and can go to num_player - 1.  For users(), etc.
  923.  */
  924. struct object * get_interactive_object(i)
  925. int i;
  926. {
  927.     int n;
  928.  
  929.     if (i >= num_player) /* love them ASSERTS() :-) */
  930.     fatal("Get interactive (%d) with only %d players!", i, num_player);
  931.  
  932.     for (n = 0; n < MAX_PLAYERS; n++)
  933.     if (all_players[n])
  934.         if (!(i--))
  935.         return(all_players[n]->ob);
  936.  
  937.     fatal("Get interactive: player %d not found! (num_players = %d)",
  938.         i, num_player);
  939.     return 0;    /* Just to satisfy some compiler warnings */
  940. }
  941.  
  942. void new_player(new_socket, addr, len)
  943.     int new_socket;
  944.     struct sockaddr_in *addr;
  945.     int len;
  946. {
  947.     int i;
  948.     char *p;
  949.    
  950. #ifndef MSDOS
  951. #ifdef ACCESS_RESTRICTED
  952.     void *class;
  953.  
  954.     if (!(class = allow_host_access (new_socket, new_socket)))
  955.       return;
  956. #else
  957.     if(allow_host_access(new_socket))
  958.     return;
  959. #endif
  960. #endif
  961.     if (d_flag > 1)
  962.     debug_message("New player at socket %d.\n", new_socket);
  963.     for (i=0; i<MAX_PLAYERS; i++) {
  964.     struct object *ob;
  965.     struct svalue *ret;
  966.     extern struct object *master_ob;
  967.     
  968.     if (all_players[i] != 0)
  969.         continue;
  970.     assert_master_ob_loaded();
  971.     command_giver = master_ob;
  972.     master_ob->interactive =
  973.         (struct interactive *)xalloc(sizeof (struct interactive));
  974.     master_ob->interactive->default_err_message = 0;
  975.     master_ob->flags |= O_ONCE_INTERACTIVE;
  976.     /* This initialization is not pretty. */
  977.     master_ob->interactive->ob = master_ob;
  978.     master_ob->interactive->text[0] = '\0';
  979.     master_ob->interactive->input_to = 0;
  980.     master_ob->interactive->closing = 0;
  981.     master_ob->interactive->snoop_on = 0;
  982.     master_ob->interactive->snoop_by = 0;
  983. #ifdef PORTALS
  984.     master_ob->interactive->out_portal = 0;
  985.     master_ob->interactive->portal_socket = 0;
  986.     master_ob->interactive->from_portal = 0;
  987. #endif /* PORTALS */
  988.     master_ob->interactive->text_end = 0;
  989.     master_ob->interactive->text_start = 0;
  990.     master_ob->interactive->do_close = 0;
  991.     master_ob->interactive->noecho = 0;
  992.     master_ob->interactive->trace_level = 0;
  993.     master_ob->interactive->trace_prefix = 0;
  994.     master_ob->interactive->last_time = current_time;
  995.     master_ob->interactive->ed_buffer = 0;
  996.     master_ob->interactive->message_length=0;
  997. #ifdef MUDWHO
  998.         master_ob->interactive->login_time = current_time;
  999. #endif
  1000.     all_players[i] = master_ob->interactive;
  1001.     all_players[i]->socket = new_socket;
  1002.     set_prompt("> ");
  1003. #if 1
  1004.     memcpy((char *)&all_players[i]->addr, (char *)addr, len);
  1005. #else
  1006.     getpeername(new_socket, (struct sockaddr *)&all_players[i]->addr,
  1007.             &len);
  1008. #endif
  1009.  
  1010. #ifdef ACCESS_RESTRICTED
  1011.         all_players[i]->access_class = class;
  1012. #endif
  1013.     num_player++;
  1014.     /*
  1015.      * The player object has one extra reference.
  1016.      * It is asserted that the master_ob is loaded.
  1017.      */
  1018.     add_ref(master_ob, "new_player");
  1019.     ret = apply_master_ob("connect", 0);
  1020.     if (ret == 0 || ret->type != T_OBJECT) {
  1021.         remove_interactive(master_ob);
  1022.         return;
  1023.     }
  1024.     /*
  1025.      * There was an object returned from connect(). Use this as the
  1026.      * player object.
  1027.      */
  1028.     ob = ret->u.ob;
  1029.     ob->interactive = master_ob->interactive;
  1030.     ob->interactive->ob = ob;
  1031.     ob->flags |= O_ONCE_INTERACTIVE;
  1032.     master_ob->flags &= ~O_ONCE_INTERACTIVE;
  1033.     add_message(MESSAGE_FLUSH);
  1034.     master_ob->interactive = 0;
  1035.     free_object(master_ob, "reconnect");
  1036.     add_ref(ob, "new_player");
  1037.     command_giver = ob;
  1038.         if (f_ip_demon_wr != NULL) {
  1039. /*printf("sent hname %s\n:", query_ip_number(ob));*/
  1040.             fprintf(f_ip_demon_wr, "%s\n", query_ip_number(ob));
  1041.             fflush(f_ip_demon_wr);
  1042.         }
  1043.     logon(ob);
  1044.     flush_all_player_mess();
  1045.     return;
  1046.     }
  1047.     p = "Lpmud is full. Come back later.\r\n";
  1048.     write(new_socket, p, strlen(p));
  1049.     close(new_socket);
  1050. }
  1051.  
  1052. int call_function_interactive(i, str)
  1053.     struct interactive *i;
  1054.     char *str;
  1055. {
  1056.     char *function;
  1057.     struct object *ob;
  1058.  
  1059.     if (!i->input_to)
  1060.     return 0;
  1061.     /*
  1062.      * Special feature: input_to() has been called to setup
  1063.      * a call to a function.
  1064.      */
  1065.     if (i->input_to->ob->flags & O_DESTRUCTED) {
  1066.     /* Sorry, the object has selfdestructed ! */
  1067.     free_object(i->input_to->ob, "call_function_interactive");
  1068.     free_sentence(i->input_to);
  1069.     i->input_to = 0;
  1070.     return 0;
  1071.     }
  1072.     free_object(i->input_to->ob, "call_function_interactive");
  1073.     function = string_copy(command_giver->interactive->input_to->function);
  1074.     ob = i->input_to->ob;
  1075.     free_sentence(i->input_to);
  1076.     /*
  1077.      * We must clear this reference before the call to apply(), because
  1078.      * someone might want to set up a new input_to().
  1079.      */
  1080.     i->input_to = 0;
  1081.     /*
  1082.      * Now we set current_object to this object, so that input_to will
  1083.      * work for static functions.
  1084.      */
  1085.     push_constant_string(str);
  1086.     current_object = ob;
  1087.     (void)apply(function, ob, 1);
  1088.     free(function);
  1089.     flush_all_player_mess();
  1090.     return 1;
  1091. }
  1092.  
  1093. int set_call(ob, sent, noecho)
  1094.     struct object *ob;
  1095.     struct sentence *sent;
  1096.     int noecho;
  1097. {
  1098.     struct object *save = command_giver;
  1099.     if (ob == 0 || sent == 0)
  1100.     return 0;
  1101.     if (ob->interactive == 0 || ob->interactive->input_to)
  1102.     return 0;
  1103.     ob->interactive->input_to = sent;
  1104.     ob->interactive->noecho = noecho;
  1105.     command_giver = ob;
  1106.     if (noecho)
  1107.     add_message("%c%c%c", IAC, WILL, TELOPT_ECHO);
  1108.     command_giver = save;
  1109.     return 1;
  1110. }
  1111.  
  1112. void show_info_about(str, room, i)
  1113.     char *str, *room;
  1114.     struct interactive *i;
  1115. {
  1116.     struct hostent *hp = 0;
  1117.  
  1118. #if 0
  1119.     hp = gethostbyaddr(&i->addr.sin_addr.s_addr, 4, AF_INET);
  1120. #endif
  1121.     add_message("%-15s %-15s %s\n",
  1122.         hp ? hp->h_name : inet_ntoa(i->addr.sin_addr), str, room);
  1123. }
  1124.  
  1125. void remove_all_players()
  1126. {
  1127.     int i;
  1128.  
  1129.     for (i=0; i<MAX_PLAYERS; i++) {
  1130.     if (all_players[i] == 0)
  1131.         continue;
  1132.     command_giver = all_players[i]->ob;
  1133.     (void)apply("quit", all_players[i]->ob, 0);
  1134.     }
  1135. }
  1136.  
  1137. void set_prompt(str)
  1138.     char *str;
  1139. {
  1140.     command_giver->interactive->prompt = str;
  1141. }
  1142.  
  1143. /*
  1144.  * Print the prompt, but only if input_to not is disabled.
  1145.  */
  1146. void print_prompt()
  1147. {
  1148.     if (command_giver == 0)
  1149.     fatal("command_giver == 0.\n");
  1150.     if (command_giver->interactive->input_to == 0) {
  1151.     add_message(command_giver->interactive->prompt);
  1152.     if (1) { /* add test for heart_beat later */
  1153.             flush_all_player_mess();
  1154.     }
  1155.     }
  1156. }
  1157.  
  1158. /*
  1159.  * Let object 'me' snoop object 'you'. If 'you' is 0, then turn off
  1160.  * snooping.
  1161.  */
  1162. void set_snoop(me, you)
  1163.     struct object *me, *you;
  1164. {
  1165.     struct interactive *on = 0, *by = 0, *tmp;
  1166.     int i;
  1167.  
  1168.     if (me->flags & O_DESTRUCTED)
  1169.     return;
  1170.     if (you && (you->flags & O_DESTRUCTED))
  1171.     return;
  1172.     for(i=0; i<MAX_PLAYERS && (on == 0 || by == 0); i++) {
  1173.     if (all_players[i] == 0)
  1174.         continue;
  1175.     if (all_players[i]->ob == me)
  1176.         by = all_players[i];
  1177.     else if (all_players[i]->ob == you)
  1178.         on = all_players[i];
  1179.     }
  1180.     if (you == 0) {
  1181.     if (by == 0)
  1182.         error("Could not find myself to stop snoop.\n");
  1183.     add_message("Ok.\n");
  1184.     if (by->snoop_on == 0)
  1185.         return;
  1186.     by->snoop_on->snoop_by = 0;
  1187.     by->snoop_on = 0;
  1188.     return;
  1189.     }
  1190.     if (on == 0 || by == 0) {
  1191.     add_message("Failed.\n");
  1192.     return;
  1193.     }
  1194.     if (by->snoop_on) {
  1195.     by->snoop_on->snoop_by = 0;
  1196.     by->snoop_on = 0;
  1197.     }
  1198.     if (on->snoop_by) {
  1199.     add_message("Busy.\n");
  1200.     return;
  1201.     }
  1202.     /*
  1203.      * Protect against snooping loops.
  1204.      */
  1205.     for (tmp = on; tmp; tmp = tmp->snoop_on) {
  1206.     if (tmp == by) {
  1207.         add_message("Busy.\n");
  1208.         return;
  1209.     }
  1210.     }
  1211.     on->snoop_by = by;
  1212.     by->snoop_on = on;
  1213.     add_message("Ok.\n");
  1214.     return;
  1215. }
  1216.  
  1217. /*
  1218.  * Let object 'me' snoop object 'you'. If 'you' is 0, then turn off
  1219.  * snooping.
  1220.  *
  1221.  * This routine is almost identical to the old set_snoop. The main
  1222.  * difference is that the routine writes nothing to player directly,
  1223.  * all such communication is taken care of by the mudlib. It communicates
  1224.  * with master.c in order to find out if the operation is permissble or
  1225.  * not. The old routine let everyone snoop anyone. This routine also returns
  1226.  * 0 or 1 depending on success.
  1227.  */
  1228. int new_set_snoop(me, you)
  1229.     struct object *me, *you;
  1230. {
  1231.     struct interactive *on = 0, *by = 0, *tmp;
  1232.     int i;
  1233.     struct svalue *ret;
  1234.  
  1235.     /* Stop if people managed to quit before we got this far */
  1236.     if (me->flags & O_DESTRUCTED)
  1237.     return 0;
  1238.     if (you && (you->flags & O_DESTRUCTED))
  1239.     return 0;
  1240.  
  1241.     /* Find the snooper & snopee */
  1242.     for(i = 0 ; i < MAX_PLAYERS && (on == 0 || by == 0); i++) 
  1243.     {
  1244.     if (all_players[i] == 0)
  1245.         continue;
  1246.     if (all_players[i]->ob == me)
  1247.         by = all_players[i];
  1248.     else if (all_players[i]->ob == you)
  1249.         on = all_players[i];
  1250.     }
  1251.  
  1252.     /* Illegal snoop attempt by null object */
  1253.     if (!current_object->eff_user)
  1254.     return 0;
  1255.  
  1256.     /* Check for permissions with valid_snoop in master */
  1257.     push_object(me);
  1258.     if (you == 0)
  1259.     push_number(0);
  1260.     else
  1261.     push_object(you);
  1262.     ret = apply_master_ob("valid_snoop", 2);
  1263.  
  1264.     if (!ret || ret->type != T_NUMBER || ret->u.number == 0)
  1265.     return 0;
  1266.  
  1267.     /* Stop snoop */
  1268.     if (you == 0) 
  1269.     {
  1270.     if (by == 0)
  1271.         error("Could not find snooper to stop snoop on.\n");
  1272.     if (by->snoop_on == 0)
  1273.         return 1;
  1274.     by->snoop_on->snoop_by = 0;
  1275.     by->snoop_on = 0;
  1276.     return 1;
  1277.     }
  1278.  
  1279.     /* Strange event, but possible, so test for it */
  1280.     if (on == 0 || by == 0)
  1281.     return 0;
  1282.  
  1283.     /* Protect against snooping loops */
  1284.     for (tmp = on; tmp; tmp = tmp->snoop_on) 
  1285.     {
  1286.     if (tmp == by) 
  1287.         return 0;
  1288.     }
  1289.  
  1290.     /* Terminate previous snoop, if any */
  1291.     if (by->snoop_on) 
  1292.     {
  1293.     by->snoop_on->snoop_by = 0;
  1294.     by->snoop_on = 0;
  1295.     }
  1296.     if (on->snoop_by)
  1297.     {
  1298.     on->snoop_by->snoop_on = 0;
  1299.     on->snoop_by = 0;
  1300.     }
  1301.  
  1302.     on->snoop_by = by;
  1303.     by->snoop_on = on;
  1304.     return 1;
  1305.     
  1306. }
  1307.  
  1308. #define    TS_DATA        0
  1309. #define    TS_IAC        1
  1310. #define    TS_WILL        2
  1311. #define    TS_WONT        3
  1312. #define    TS_DO        4
  1313. #define    TS_DONT        5
  1314.  
  1315. void telnet_neg(to, from)
  1316.     char *to, *from;
  1317. {
  1318.     int state = TS_DATA;
  1319.     int ch;
  1320.     char *first = to;
  1321.  
  1322.     while(1) {
  1323.     ch = (*from++ & 0xff);
  1324.     switch(state) {
  1325.     case TS_DATA:
  1326.         switch(ch) {
  1327.         case IAC:
  1328.         state = TS_IAC;
  1329.         continue;
  1330.         case '\b':    /* Backspace */
  1331.         case 0x7f:    /* Delete */
  1332.         if (to <= first)
  1333.             continue;
  1334.         to -= 1;
  1335.         continue;
  1336.         default:
  1337.         if (ch & 0x80) {
  1338.             if (d_flag) debug_message("Tel_neg: 0x%x\n", ch);
  1339.             continue;
  1340.         }
  1341.         *to++ = ch;
  1342.         if (ch == 0)
  1343.             return;
  1344.         continue;
  1345.         }
  1346.     case TS_IAC:
  1347.         switch(ch) {
  1348.         case WILL:
  1349.         state = TS_WILL;
  1350.         continue;
  1351.         case WONT:
  1352.         state = TS_WONT;
  1353.         continue;
  1354.         case DO:
  1355.         state = TS_DO;
  1356.         continue;
  1357.         case DONT:
  1358.         state = TS_DONT;
  1359.         continue;
  1360.         case DM:
  1361.         break;
  1362.         case NOP:
  1363.         case GA:
  1364.         default:
  1365.         break;
  1366.         }
  1367.         state = TS_DATA;
  1368.         continue;
  1369.     case TS_WILL:
  1370.         if (d_flag) debug_message("Will %s\n", telopts[ch]);
  1371.         state = TS_DATA;
  1372.         continue;
  1373.     case TS_WONT:
  1374.         if (d_flag) debug_message("Wont %s\n", telopts[ch]);
  1375.         state = TS_DATA;
  1376.         continue;
  1377.     case TS_DO:
  1378.         if (d_flag) debug_message("Do %s\n", telopts[ch]);
  1379.         state = TS_DATA;
  1380.         continue;
  1381.     case TS_DONT:
  1382.         if (d_flag) debug_message("Dont %s\n", telopts[ch]);
  1383.         state = TS_DATA;
  1384.         continue;
  1385.     default:
  1386.         if (d_flag) debug_message("Bad state: 0x%x\n", state);
  1387.         state = TS_DATA;
  1388.         continue;
  1389.     }
  1390.     }
  1391. }
  1392.  
  1393. #define IPSIZE 200
  1394. static struct ipentry {
  1395.     long addr;
  1396.     char *name;
  1397. } iptable[IPSIZE];
  1398. static int ipcur;
  1399.  
  1400. char *query_ip_name(ob)
  1401.     struct object *ob;
  1402. {
  1403.     int i;
  1404.  
  1405.     if (ob == 0)
  1406.     ob = command_giver;
  1407.     if (!ob || ob->interactive == 0)
  1408.     return 0;
  1409.     for(i = 0; i < IPSIZE; i++) {
  1410.     if (iptable[i].addr == ob->interactive->addr.sin_addr.s_addr &&
  1411.         iptable[i].name)
  1412.         return iptable[i].name;
  1413.     }
  1414.     return inet_ntoa(ob->interactive->addr.sin_addr);
  1415. }
  1416.  
  1417. static void add_ip_entry(addr, name)
  1418. long addr;
  1419. char *name;
  1420. {
  1421.     int i;
  1422.  
  1423.     for(i = 0; i < IPSIZE; i++) {
  1424.     if (iptable[i].addr == addr)
  1425.         return;
  1426.     }
  1427.     iptable[ipcur].addr = addr;
  1428.     if (iptable[ipcur].name)
  1429.     free_string(iptable[ipcur].name);
  1430.     iptable[ipcur].name = make_shared_string(name);
  1431.     ipcur = (ipcur+1) % IPSIZE;
  1432. }
  1433.  
  1434. char *query_ip_number(ob)
  1435.     struct object *ob;
  1436. {
  1437.     if (ob == 0)
  1438.     ob = command_giver;
  1439.     if (!ob || ob->interactive == 0)
  1440.     return 0;
  1441.     return inet_ntoa(ob->interactive->addr.sin_addr);
  1442. }
  1443.  
  1444. #ifndef INET_NTOA_OK
  1445. /*
  1446. Note: if the address string is "a.b.c.d" the address number is
  1447.       a * 256^3 + b * 256^2 + c * 256 + d
  1448.  
  1449. */
  1450.  
  1451. char *inet_ntoa(ad)
  1452.     struct in_addr ad;
  1453. {
  1454.     u_long s_ad;
  1455.     int a, b, c, d;
  1456.     static char addr[20]; /* 16 + 1 should be enough */
  1457.  
  1458.     s_ad = ad.s_addr;
  1459.     d = s_ad % 256;
  1460.     s_ad /= 256;
  1461.     c = s_ad % 256;
  1462.     s_ad /= 256;
  1463.     b = s_ad % 256;
  1464.     a = s_ad / 256;
  1465.     sprintf(addr, "%d.%d.%d.%d", a, b, c, d);
  1466.     return addr;
  1467. }
  1468. #endif /* INET_NTOA_OK */
  1469.  
  1470. char *query_host_name() {
  1471.     static char name[20];
  1472.     
  1473.     gethostname(name, sizeof name);
  1474.     name[sizeof name - 1] = '\0';    /* Just to make sure */
  1475.     return name;
  1476. }
  1477.  
  1478. struct object *query_snoop(ob)
  1479.     struct object *ob;
  1480. {
  1481.     if (ob->interactive->snoop_by == 0)
  1482.     return 0;
  1483.     return ob->interactive->snoop_by->ob;
  1484. }
  1485.  
  1486. int query_idle(ob)
  1487.     struct object *ob;
  1488. {
  1489.     if (!ob->interactive)
  1490.     error("query_idle() of non-interactive object.\n");
  1491.     return current_time - ob->interactive->last_time;
  1492. }
  1493.  
  1494. void notify_no_command() {
  1495.     char *p,*m;
  1496.  
  1497.     if (!command_giver->interactive)
  1498.     return;
  1499.     p = command_giver->interactive->default_err_message;
  1500.     if (p) {
  1501.     m = process_string(p); /* We want 'value by function call' /JnA */
  1502.     if (!shadow_catch_message(command_giver, m))
  1503.         add_message(m);
  1504.     if (m != p)
  1505.         free(m);
  1506.     free_string(p);
  1507.     command_giver->interactive->default_err_message = 0;
  1508.     }
  1509.     else {
  1510.     add_message("What ?\n");
  1511.     }
  1512. }
  1513.  
  1514. void clear_notify() {
  1515.     if (!command_giver->interactive)
  1516.     return;
  1517.     if (command_giver->interactive->default_err_message) {
  1518.     free_string(command_giver->interactive->default_err_message);
  1519.     command_giver->interactive->default_err_message = 0;
  1520.     }
  1521. }
  1522.  
  1523. void set_notify_fail_message(str)
  1524.     char *str;
  1525. {
  1526.     if (!command_giver || !command_giver->interactive)
  1527.     return;
  1528.     clear_notify();
  1529.     if (command_giver->interactive->default_err_message)
  1530.     free_string(command_giver->interactive->default_err_message);
  1531.     command_giver->interactive->default_err_message = make_shared_string(str);
  1532. }
  1533.  
  1534. int replace_interactive(ob, obfrom, /*IGN*/name)
  1535.     struct object *ob;
  1536.     struct object *obfrom;
  1537.     char *name;
  1538. {
  1539.     /* marion
  1540.      * i see no reason why to restrict this, besides - the length
  1541.      * (was) missing to strncmp()
  1542.      * JnA: There is every reason to restrict this.
  1543.      *      Otherwise I can write my own player object without any security
  1544.      *      at all!
  1545.      */
  1546.     struct svalue *v;
  1547.  
  1548.     push_string(name, STRING_CONSTANT);
  1549.     v = apply_master_ob("valid_exec", 1);
  1550.     if (!v || v->type != T_NUMBER || v->u.number == 0)
  1551.     return 0;
  1552. /*
  1553.     if (strcmp(name, "secure/login.c") != 0)
  1554.     return 0;
  1555. */
  1556.     /* fprintf(stderr,"DEBUG: %s,%s\n",ob->name,obfrom->name); */
  1557.     if (ob->interactive)
  1558.     error("Bad argument1 to exec()\n");
  1559.     if (!obfrom->interactive)
  1560.     error("Bad argument2 to exec()\n");
  1561.     if (obfrom->interactive->message_length) {
  1562.         struct object *save;
  1563.         save=command_giver;
  1564.         command_giver=obfrom;
  1565.         add_message(MESSAGE_FLUSH);
  1566.     command_giver=save;
  1567.     }
  1568.     ob->interactive = obfrom->interactive;
  1569.     obfrom->interactive = 0;
  1570.     ob->interactive->ob = ob;
  1571.     ob->flags |= O_ONCE_INTERACTIVE;
  1572.     obfrom->flags &= ~O_ONCE_INTERACTIVE;
  1573.     add_ref(ob, "exec");
  1574.     free_object(obfrom, "exec");
  1575.     if (obfrom == command_giver) command_giver = ob;
  1576.     return 1;
  1577. }
  1578.  
  1579. #ifdef DEBUG
  1580. /*
  1581.  * This is used for debugging reference counts.
  1582.  */
  1583.  
  1584. void update_ref_counts_for_players() {
  1585.     int i;
  1586.  
  1587.     for (i=0; i<MAX_PLAYERS; i++) {
  1588.     if (all_players[i] == 0)
  1589.         continue;
  1590.     all_players[i]->ob->extra_ref++;
  1591.     if (all_players[i]->input_to)
  1592.         all_players[i]->input_to->ob->extra_ref++;
  1593.     }
  1594. }
  1595. #endif /* DEBUG */
  1596.  
  1597. #ifdef MUDWHO
  1598.  
  1599. char mudwhoid[200];
  1600.  
  1601. sendmudwhoinfo()
  1602. {
  1603.     struct object *ob;
  1604.     int i;
  1605.     static int last_called_time;
  1606.  
  1607.     if (current_time - last_called_time < MUDWHO_REFRESH_TIME)
  1608.     return;
  1609.  
  1610.     last_called_time = get_current_time();
  1611.  
  1612.     rwhocli_pingalive();
  1613.  
  1614.     for (i = 0; i < num_player; i++) {
  1615.     ob = get_interactive_object(i);
  1616.     if (ob->living_name)
  1617.     {
  1618.         sscanf(ob->name,"%*[^#]#%s",mudwhoid);
  1619.         strcat(mudwhoid,"@");
  1620.         strcat(mudwhoid,MUDWHO_NAME);
  1621.         rwhocli_userlogin(mudwhoid,ob->living_name,
  1622.         ob->interactive->login_time);
  1623.     }
  1624.     }
  1625. }
  1626. sendmudwhologout(ob)
  1627. struct object *ob;
  1628. {
  1629.     if (ob->interactive)
  1630.     {
  1631.         sscanf(ob->name,"%*[^#]#%s",mudwhoid);
  1632.         strcat(mudwhoid,"@");
  1633.         strcat(mudwhoid,MUDWHO_NAME);
  1634.         rwhocli_userlogout(mudwhoid);
  1635.     }
  1636. }
  1637. #endif
  1638.